/*
 * Copyright (c) 2010, okazoh_tk. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *  - Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "alkes/text/EmbedGlyphProvider.h"

namespace alkes {

struct EmbedFontData {
    uint8_t width;
    uint8_t height;
    uint8_t ascent;
    uint8_t descent;
};

struct EmbedFontBboxData {
    uint8_t ymin;
    uint8_t ymax;
};

static EmbedFontData s_embed_font_data = {
     6, // width
    13, // height
     9, // ascent
     4, // descent
};

static const uint8_t s_system_font[] = {
#include "./system_font_data.inl"
};

static const EmbedFontBboxData s_system_font_bbox[] = {
#include "./system_font_bbox.inl"
};

EmbedGlyphProvider* EmbedGlyphProvider::create()
{
    return new EmbedGlyphProvider();
}

void EmbedGlyphProvider::destroy()
{
    delete this;
}

EmbedGlyphProvider::EmbedGlyphProvider()
{
    TextMetrics metrics;

    metrics.height = s_embed_font_data.height;
    metrics.max_width = s_embed_font_data.width;
    metrics.ascent = s_embed_font_data.ascent;
    metrics.descent = s_embed_font_data.descent;

    initTextMetrics(metrics);
}

EmbedGlyphProvider::~EmbedGlyphProvider()
{
}

bool EmbedGlyphProvider::onGetGlyphMetrics(int32_t ch, GlyphMetrics& metrics)
{
    if (0x7f < ch)
        return false;

    metrics.x = 0;
    metrics.y = 0;
    metrics.bbox_width = s_embed_font_data.width;   // fixed bbox
    metrics.bbox_height = s_embed_font_data.height;
    metrics.advance = s_embed_font_data.width;

    return true;
}

bool EmbedGlyphProvider::onRenderChar(int32_t ch, RenderBuffer& target, GlyphMetrics& metrics)
{
    if (!onGetGlyphMetrics(ch, metrics))
        return false;

    if (ch < 0x20)
        return true;

    // Copy bounding box only.
    const uint8_t* p = s_system_font + ch * 10;
    int y = s_system_font_bbox[ch].ymin;
    int x;
    uint8_t* dst = target.buffer + y * target.pitch;
    int i = y * s_embed_font_data.width;
    int gap = target.width < s_embed_font_data.width ? (s_embed_font_data.width - target.width) : 0;

    for (; y < s_system_font_bbox[ch].ymax && y < target.height; ++y)
    {
        for (x = 0; x < s_embed_font_data.width && x < target.width; ++x, ++i)
        {
            *(dst + x) = (p[i >> 3] & (0x80 >> (i % 8))) ? 0xff : 0;
        }
        i += gap;
        dst += target.pitch;
    }

    return true;
}


}
